package com.teamtwoseven.todo;

import java.util.Arrays;
import android.app.AlertDialog;
import android.app.ExpandableListActivity;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ExpandableListView;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.AdapterView.OnItemSelectedListener;

/**
 * This is the first screen the user sees after logging in. This Activity runs
 * from login to logout.
 * 
 * @author teamtwoseven
 */
public class Main extends ExpandableListActivity implements OnClickListener {

	public static Item[] items;
	
	private Singleton singleton;
	private long userRowID;
	private Storage storage;
	private Button bSettings, bLogout, bNewItem, bViewMap;
	private ExpandableListView expList;
	private ListAdapter listAdapter;
	private Spinner spinner;

	/**
	 * Called when the activity is first created.
	 * 
	 * @param savedInstanceState
	 * 			allows instance data to be stored
	 */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
		
		getUser(); // sets userRowID, storage, and the welcome text

		bSettings = (Button) findViewById(R.id.main_bSettings);
		bNewItem = (Button) findViewById(R.id.main_bNewItem);
		bLogout = (Button) findViewById(R.id.main_bLogout);
		bViewMap = (Button) findViewById(R.id.main_bViewMap);

		bSettings.setOnClickListener(this);
		bNewItem.setOnClickListener(this);
		bLogout.setOnClickListener(this);
		bViewMap.setOnClickListener(this);

		// The spinner allows the user to select which items the list displays
		spinner = (Spinner) findViewById(R.id.main_spinner);
		ArrayAdapter<CharSequence> adapter =
			ArrayAdapter.createFromResource(this, R.array.filter_type,
			android.R.layout.simple_spinner_item);
		adapter.setDropDownViewResource(
			android.R.layout.simple_spinner_dropdown_item);
		spinner.setAdapter(adapter);
		spinner.setOnItemSelectedListener(new SpinnerListener());
		spinner.setSelection(0); // selects "All Items"

		expList = getExpandableListView(); // shows the list of items
	}

	/**
	 * Updates the list when the user returns to this Activity from another.
	 */
	@Override
	protected void onResume() {
		super.onResume();
		updateList();
	}

	/**
	 * Gets the row ID of the current user's stored info. Also sets the welcome
	 * text to display the user's full name if it is less than 22 characters;
	 * up to 22 characters of the user's first name otherwise.
	 */
	public void getUser() {
		singleton = Singleton.getInstance();
		userRowID = singleton.getUserRowID();
		storage = new Storage(Main.this);
		
		String name = storage.getFullName(userRowID);

		if (name.length() > 22) {
			name = name.substring(0, 22);
			if (name.substring(1, 21).contains(" ")) {
				name = name.substring(0, name.indexOf(" "));
			}
		}

		TextView tvWelcome = (TextView) findViewById(R.id.main_tvWelcome);
		tvWelcome.setText("Welcome, " + name + "!");
	}
	
	/**
	 * When they end, Activities can return a resultCode to an Activity that
	 * started them for a result. This method handles resultCodes 1, 2, and 3.
	 * 
	 * @param requestCode
	 * 			supplied when the Activity was started; ignored here
	 * @param resultCode
	 * 			signifies why an Activity ended
	 * @param data
	 * 			any extra data from the ended Activity; ignored here
	 */
	protected void onActivityResult(int requestCode, int resultCode,
		Intent data) {
		
		super.onActivityResult(requestCode, resultCode, data);
		switch (resultCode) {
		case 1: // The user clicked logout; open login screen, end all others
			startActivity(new Intent("com.teamtwoseven.todo.SYSSTART"));
			finish();
			break;
		case 2: // The user clicked settings; open the settings screen
			startActivityForResult(
				new Intent("com.teamtwoseven.todo.CHANGEPASSWORD"), 1);
			break;
		case 3: // The user changed their stored name; update the welcome text
			getUser();
			break;
		case 4: // The user added a new item; reset the list to all items so
				// the item shows up when the user returns to Main
			spinner.setSelection(0);
			break;
		}
	}

	/**
	 * Updates the list to the most recent spinner selection. If there are no
	 * items to display and the filter isn't "All Items", displays all items.
	 */
	public void updateList() {
		int spinnerPosition;
		
		switch (spinnerPosition = spinner.getSelectedItemPosition()) {
		case 0: // "All Items"
			Main.items = storage.getAllItems(userRowID);
			break;
		case 1: // "Custom Search"
			// Do nothing; Main.items holds the search results or is empty and
			// will be reset below
			break;
		case 2: // "Not Completed"
			Main.items = storage.getSpecificItems(userRowID,
				Storage.I_KEY_ISDONE + "='false'");
			break;
		case 3: // "Completed"
			Main.items = storage.getSpecificItems(userRowID,
				Storage.I_KEY_ISDONE + "='true'");
			break;
		case 4: // "Personal"
			Main.items = storage.getSpecificItems(userRowID,
				Storage.I_KEY_CATEGORY + "='Personal'");
			break;
		case 5: // "School"
			Main.items = storage.getSpecificItems(userRowID,
				Storage.I_KEY_CATEGORY + "='School'");
			break;
		case 6: // "Work"
			Main.items = storage.getSpecificItems(userRowID,
				Storage.I_KEY_CATEGORY + "='Work'");
			break;
		case 7: // "Miscellaneous"
			Main.items = storage.getSpecificItems(userRowID,
				Storage.I_KEY_CATEGORY + "='Miscellaneous'");
			break;
		}
		
		if ((Main.items == null) || (Main.items.length < 1)) {
			Main.items = new Item[0];
			if (spinnerPosition > 1) {
				popupDialog("No items were found of the type " + "\"" +
					spinner.getSelectedItem() + "\". " +
					"Showing All Items instead.", false);
			}
			if (spinnerPosition > 0) {
				spinner.setSelection(0);
				// This method is called again by setting the spinner selection
				// No need to do the last three lines twice
				return; 
			}
		}
		
		Arrays.sort(Main.items);
		listAdapter = new ListAdapter(this, Main.items, this);
		expList.setAdapter(listAdapter);
	}
	
	/**
	 * Displays the given message and an OK button in a dialog. If done is
	 * true, clicking OK also ends this Activity. Otherwise OK just closes the
	 * dialog.
	 * 
	 * @param message
	 * 			text to display to the user
	 * @param done
	 * 			if true, clicking OK also finishes the Activity; if false, OK
	 * 			just closes the dialog
	 */
	private void popupDialog(String message, final boolean done) {
		AlertDialog.Builder builder = new AlertDialog.Builder(this);

		builder.setMessage(message);
		builder.setCancelable(false);
		builder.setPositiveButton("OK", new DialogInterface.OnClickListener() {
			public void onClick(DialogInterface dialog, int id) {
				dialog.cancel();
				if (done) {
					finish();
				}
			}
		});
		builder.show();
	}
	
	private void deleteDialog(String message, final long rowID) {
		AlertDialog.Builder builder = new AlertDialog.Builder(this);

		builder.setMessage(message);
		builder.setCancelable(true);
		builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
			public void onClick(DialogInterface dialog, int id) {
				dialog.cancel();
			}
		});
		builder.setPositiveButton("OK", new DialogInterface.OnClickListener() {
			public void onClick(DialogInterface dialog, int id) {
				dialog.cancel();
				
				// Delete item from storage and update the list
				storage.deleteItem(userRowID, rowID);
				updateList();
			}
		});
		builder.show();
	}

	/**
	 * Handles button clicks
	 * 
	 * @param arg0
	 * 			the element that was clicked
	 */
	public void onClick(View arg0) {
		if (arg0 == bSettings) {
			startActivityForResult(
				new Intent("com.teamtwoseven.todo.CHANGEPASSWORD"), 1);
		}
		else if (arg0 == bNewItem) {
			startActivityForResult(
				new Intent("com.teamtwoseven.todo.NEWITEM"), 1);
		}
		else if (arg0 == bLogout) {
			// Open login screen, end all others
			startActivity(new Intent("com.teamtwoseven.todo.SYSSTART"));
		
			finish();
		}
		else if (arg0 == bViewMap) {
			// Open MapView Activity
			startActivity(new Intent("com.teamtwoseven.todo.VIEWMAP"));
		}
		else {
			// The element must belong to listAdapter
			Item[] list = listAdapter.getItems();
			
			for (int i = 0; i < list.length; i++) {
				if (arg0 == listAdapter.getEditButtons()[i]) {
					// Pass the itemRowID to the Edit Item screen
					
					singleton.setItemRowID(list[i].getItemID());
					startActivityForResult(
						new Intent("com.teamtwoseven.todo.EDITITEM"), 1);
					break; // found what was clicked
				}
				else if (arg0 == listAdapter.getDeleteButtons()[i]) {
					// Prompt the user to be sure they meant to delete the item
					
					deleteDialog("Click OK to permanently delete the item.",
						list[i].getItemID());
					break; // found what was clicked
				}
				else if (arg0 == listAdapter.getLocationButtons()[i]) {
					
					String location = list[i].getLocation();
					Intent intent = new Intent(Main.this, NewLocation.class);
					intent.putExtra("location text", location);
					startActivity(intent);
					break; // found what was clicked
				}
				else if (arg0 == listAdapter.getCheckBoxes()[i]) {
					// Set corresponding item done if to-do, to-do if done
					
					long itemRowID = list[i].getItemID();
					
					if (listAdapter.getItems()[i].isDone()) {
						storage.setItemUndone(userRowID, itemRowID);
					}
					else {
						storage.setItemDone(userRowID, itemRowID);
					}
					
					listAdapter.toggleDone(i);
					break; // found what was clicked
				}
			}
		}
	}
	
	/**
	 * Handles the user pressing the back key
	 */
	@Override
	public void onBackPressed() {
		startActivity(new Intent("com.teamtwoseven.todo.SYSSTART"));
		finish();
	}
	
	/**
	 * Called when this Activity ends. Sets the userRowID in Singleton to -1 to
	 * ensure this user's information can only be accessed by logging in again.
	 */
	@Override
	public void finish() {
		Singleton.getInstance().setUserRowID(-1);
		super.finish();
	}

	/**
	 * Monitors the category spinner.
	 */
	private class SpinnerListener implements OnItemSelectedListener {

		/**
		 * Sets the list or launches ItemSearch based on the spinner selection
		 * 
		 * @param parent
		 * 			the category menu
		 * @param view
		 * 			the View for the category menu
		 * @param pos
		 * 			the index of the selected category in the menu; 0 is the
		 * 			top index
		 * @param id
		 * 			the menu row ID of the selected category
		 */
		public void onItemSelected(AdapterView<?> parent, View view, int pos,
			long id) {
			
			if (pos == 1) { // "Custom Search" was selected
				startActivityForResult(
					new Intent("com.teamtwoseven.todo.ITEMSEARCH"), 1);
			}
			else {
				updateList();
			}
		}

		/**
		 * Determines what to do when nothing on the spinner menu is selected.
		 * 
		 * @param parent
		 * 			the category menu
		 */
		@SuppressWarnings("rawtypes")
		public void onNothingSelected(AdapterView parent) {
			// Do nothing.
		}
	}

	/**
	 * For jUnit tests
	 * @return field userRowID - the rowID of the current user's stored info
	 */
	public long getUserRowID() {
		return userRowID;
	}

	/**
	 * For jUnit tests
	 * @return the rowID of the current user's stored info, from singleton
	 */
	public long getSingletonUserRowID() {
		return singleton.getUserRowID();
	}

	/**
	 * For jUnit tests
	 * @return the itemRowID stored in singleton
	 */
	public long getSingletonItemRowID() {
		return singleton.getItemRowID();
	}
}